home *** CD-ROM | disk | FTP | other *** search
/ Internet Surfer: Getting Started / Internet Surfer - Getting Started (Wayzata Technology)(7231)(1995).bin / pc / mac / bonus / peter_le / talk_sou / my_libra / oostatic.uni < prev   
Text File  |  1992-04-20  |  14KB  |  497 lines

  1. unit OOStaticEdit;
  2.  
  3. { This program was written by Peter N Lewis, Mar 1992 in THINK Pascal 4.0.1 }
  4.  
  5. interface
  6.  
  7.     type
  8.         TEStaticObject = object
  9.                 window: dialogPtr;
  10.                 titem: integer;
  11.                 vcontrol, hcontrol: controlHandle;
  12.                 te: TEHandle;
  13.                 titemr: rect;
  14.                 hasgrow, drawgrow: boolean; { hasgrow -> leave room for grow icon, drawgrow -> draw it during updates }
  15.                 doubleClickTime, tripleClickTime: longInt;
  16.                 procedure Create (dlg: dialogPtr; item, width: integer; vscroll, hscroll, hasgrowb, drawgrowb: boolean);
  17.                 procedure Destroy;
  18.                 procedure Adjust;
  19.                 procedure Resize;
  20.                 procedure Draw;
  21.                 function EditMenuEnabled: boolean;
  22.                 procedure SetEditMenuItem (item: integer);
  23.                 procedure DoEditMenu (item: integer);
  24.                 procedure DoItemWhere (er: eventRecord; item: integer);
  25.                 procedure DoIdle;
  26.                 procedure DoKey (modifiers: integer; ch: char);
  27.                 procedure DoActivateDeactivate (activate: boolean);
  28.                 procedure ClickLoop;
  29.                 procedure Click (pt: point; extend: boolean);
  30.                 function WordBreak (text: ptr; pos: integer; forward: boolean): boolean;
  31.             end;
  32.  
  33. implementation
  34.  
  35.     uses
  36.         OOMainLoop, BaseGlobals, MyTypes, MyUtils, MyUtilities;
  37.  
  38.     var
  39.         teo: TEStaticObject;
  40.         teOriginalClickLoop: procPtr;
  41.  
  42. { DON'T EVEN THINK ABOUT LOOKING AT THIS CODE!!!!! }
  43.  
  44.     procedure CallCL (addr: procPtr);
  45.     inline
  46.         $205F, $4E90;
  47.  
  48.     procedure SetD0to1;
  49.     inline
  50.         $7001;
  51.  
  52.     function GetD2: longInt;
  53.     inline
  54.         $2F42, $0000;
  55.  
  56.     procedure Unlink;
  57.     inline
  58.         $4E5E;
  59.  
  60.     procedure Link;
  61.     inline
  62.         $4E56, $0000;
  63.  
  64. {$PUSH}
  65. {$D-}
  66.   { Turn debug off, lest our qute little SetD0to1 hack gets crunged by TP }
  67.     procedure CallClickLoop;  { There must be a better way to sort out this crap! }
  68.     begin
  69.         Unlink;  { This is a rediculous hack! }
  70.         CallCL(teOriginalClickLoop);
  71.         Link;
  72.         teo.ClickLoop;
  73.         SetD0to1;
  74.     end;
  75.  
  76.     function CallWordBreak (text: ptr; pos: integer): boolean;
  77.         var
  78.             d2: longInt;
  79.     begin
  80.         d2 := GetD2;
  81.         CallWordBreak := teo.WordBreak(text, pos, BAND(d2, $00020000) = 0);
  82.     end;
  83. {$POP}
  84.  
  85.     function FindEOL (te: TEHandle; loc: integer): integer;
  86.     begin
  87.         while (loc < te^^.teLength) and (ptr(longInt(te^^.hText^) + loc)^ <> 13) do
  88.             loc := loc + 1;
  89.         FindEOL := loc;
  90.     end;
  91.  
  92.     procedure TEStaticObject.Click (pt: point; extend: boolean);
  93.         var
  94.             tc, dct: longInt;
  95.             doubleclick, tripleclick: boolean;
  96.             teOriginalWordBreak: procPtr;
  97.             eol: integer;
  98.     begin
  99.         SetPort(window);
  100.         tc := TickCount;
  101.         doubleclick := tc < doubleClickTime;
  102.         tripleclick := tc < tripleClickTime;
  103.         teo := self;
  104.         teOriginalClickLoop := te^^.clikLoop;
  105.         te^^.clikLoop := @CallClickLoop;
  106.         teOriginalWordBreak := te^^.wordBreak;
  107.         if tripleclick then
  108.             SetWordBreak(@CallWordBreak, te);
  109.         if extend and tripleclick then begin{ we must fake text edit into not shrinking the selection somehow }
  110.             eol := FindEOL(te, te^^.selStart);  { if start<=clickloc<=EOL(start)<selEnd }
  111.             if (te^^.selStart <= te^^.clickloc) and (te^^.clickloc <= eol) and (eol < te^^.selEnd) then
  112.                 TESetSelect(te^^.clickloc, te^^.selEnd, te);
  113.         end;
  114.         TEClick(pt, extend, te);
  115.         tc := TickCount;
  116.         dct := GetDblTime;
  117.         doubleClickTime := tc + dct;
  118.         if doubleclick then
  119.             tripleClickTime := tc + dct;
  120.         te^^.clikLoop := teOriginalClickLoop;
  121.         te^^.wordBreak := teOriginalWordBreak;
  122.     end;
  123.  
  124.     procedure TEStaticObject.Create (dlg: dialogPtr; item, width: integer; vscroll, hscroll, hasgrowb, drawgrowb: boolean);
  125.         var
  126.             dr, vr: rect;
  127.             k: integer;
  128.             h: handle;
  129.     begin
  130.         doubleClickTime := -1;
  131.         tripleClickTime := -1;
  132.         SetPort(dlg);
  133.         window := dlg;
  134.         titem := item;
  135.         hasgrow := hasgrowb;
  136.         drawgrow := drawgrowb;
  137.         if vscroll then begin
  138.             SetRect(dr, 0, 0, 16, 100);
  139.             vcontrol := NewControl(window, dr, '', true, 0, 0, 0, scrollBarProc, 0);
  140.         end
  141.         else
  142.             vcontrol := nil;
  143.         if hscroll then begin
  144.             SetRect(dr, 0, 0, 100, 16);
  145.             hcontrol := NewControl(window, dr, '', true, 0, 0, 0, scrollBarProc, 0);
  146.         end
  147.         else
  148.             hcontrol := nil;
  149.         GetDItem(dlg, titem, k, h, dr);
  150.         titemr := dr;
  151.         EraseRect(dr);
  152.         vr := dr;
  153.         dr.right := dr.left + width;
  154.         te := TENew(dr, vr);
  155.         TEAutoView(true, te);
  156.         Resize;
  157.     end;
  158.  
  159.     procedure TEStaticObject.Destroy;
  160.     begin
  161.         TEDispose(te);
  162.         dispose(self);
  163.     end;
  164.  
  165.     procedure AdjustTE (te: TEHandle; hc, vc: integer);
  166. {Scroll the TERec around to match up to the potentially updated scrollbar}
  167. {values. This is really useful when the window resizes such that the}
  168. {scrollbars become inactive and the TERec had been previously scrolled.}
  169.         var
  170.             value: INTEGER;
  171.     begin
  172.         with te^^ do
  173.             TEScroll((viewRect.left - destRect.left) - hc, (viewRect.top - destRect.top) - (vc * lineHeight), te);
  174.     end; {AdjustTE}
  175.  
  176.     function AdjustHV (isVert: BOOLEAN; control: ControlHandle; te: TEHandle; canRedraw: BOOLEAN): integer;
  177. {Calculate the new control maximum value and current value, whether it is the horizontal or}
  178. {vertical scrollbar. The vertical max is calculated by comparing the number of lines to the}
  179. {vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document}
  180. {width to the width of the viewRect. The current values are set by comparing the offset between}
  181. {the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by}
  182. {calling ShowControl.}
  183.         var
  184.             value, lines, max: INTEGER;
  185.             oldValue, oldMax: INTEGER;
  186.     begin
  187.         oldValue := GetCtlValue(control);
  188.         oldMax := GetCtlMax(control);
  189.         with te^^ do begin
  190.             if isVert then begin
  191.                 lines := nLines;
  192.         {since nLines isn╒t right if the last character is a return, check for that case}
  193.                 if Ptr(ORD(hText^) + teLength - 1)^ = 13 then
  194.                     lines := lines + 1;
  195.                 max := lines - ((viewRect.bottom - viewRect.top) div lineHeight);
  196.             end
  197.             else
  198.                 max := destRect.right - destRect.left - (viewRect.right - viewRect.left);
  199.             if max < 0 then
  200.                 max := 0;            {check for negative values}
  201.             if isVert then
  202.                 value := (viewRect.top - destRect.top) div lineHeight
  203.             else
  204.                 value := viewRect.left - destRect.left;
  205.             if value < 0 then
  206.                 value := 0
  207.             else if value > max then
  208.                 value := max;                    {pin the value to within range}
  209.         end;
  210.         SetCtlMax(control, max);
  211.         SetCtlValue(control, value);
  212.         if canRedraw and ((max <> oldMax) or (value <> oldValue)) then
  213.             ShowControl(control);            {check to see if the control can be re-drawn}
  214.         AdjustHV := value;
  215.     end; {AdjustHV}
  216.  
  217.     procedure TEStaticObject.Adjust;
  218.         var
  219.             hc, vc: integer;
  220.     begin
  221.         vc := AdjustHV(true, vcontrol, te, false);
  222.         hc := AdjustHV(false, hcontrol, te, false);
  223.         AdjustTE(te, hc, vc);
  224.     end; {AdjustScrollValues}
  225.  
  226.     procedure TEStaticObject.Resize;
  227.         const
  228.             invis = 0;
  229.             vis = 255;
  230.             inset = 3;
  231.         var
  232.             dr, vr, r, tr: rect;
  233.             pt: point;
  234.             k: integer;
  235.             h: handle;
  236.             wd, ht: integer;
  237.             hc, vc: integer;
  238.     begin
  239.         SetPort(window);
  240.         EraseRect(titemr);
  241.         GetDItem(window, titem, k, h, tr);
  242.         titemr := tr;
  243.         InvalRect(tr);
  244.         vr := tr;
  245.         InsetRect(vr, inset, inset);
  246.         if hcontrol <> nil then
  247.             vr.bottom := vr.bottom - 15;
  248.         if vcontrol <> nil then
  249.             vr.right := vr.right - 15;
  250.         vr.bottom := vr.top + (vr.bottom - vr.top) div te^^.lineHeight * te^^.lineHeight;
  251.  
  252.         pt := vr.topleft;
  253.         SubPt(te^^.viewRect.topleft, pt);
  254.         OffsetRect(te^^.destRect, pt.h, pt.v);
  255.  
  256.         te^^.viewRect := vr;
  257.  
  258.         if vcontrol <> nil then begin
  259.             vcontrol^^.contrlVis := invis;
  260.             MoveControl(vcontrol, tr.right - 16, tr.top);
  261.             ht := tr.bottom - tr.top;
  262.             if hasgrow then
  263.                 ht := ht - 15;
  264.             SizeControl(vcontrol, 16, ht);
  265.             vc := AdjustHV(true, vcontrol, te, false);
  266.             vcontrol^^.contrlVis := vis;
  267.         end;
  268.         if hcontrol <> nil then begin
  269.             hcontrol^^.contrlVis := invis;
  270.             MoveControl(hcontrol, tr.left, tr.bottom - 16);
  271.             ht := tr.right - tr.left;
  272.             if hasgrow or (vcontrol <> nil) then
  273.                 ht := ht - 15;
  274.             SizeControl(hcontrol, ht, 16);
  275.             hc := AdjustHV(false, hcontrol, te, false);
  276.             hcontrol^^.contrlVis := vis;
  277.         end;
  278.         AdjustTE(te, hc, vc);
  279.     end;
  280.  
  281.     procedure TEStaticObject.Draw;
  282.         var
  283.             r: rect;
  284.             pt: point;
  285.             k: integer;
  286.             h: handle;
  287.     begin
  288.         GetDItem(window, titem, k, h, r);
  289.         EraseRect(r);
  290.         if drawgrow then begin
  291.             DrawGrowIcon(window);
  292.         end;
  293.         if vcontrol <> nil then begin
  294.             Draw1Control(vcontrol);
  295.         end;
  296.         if hcontrol <> nil then begin
  297.             Draw1Control(hcontrol);
  298.         end;
  299.         EraseRect(te^^.viewRect);
  300.         TEUpdate(te^^.viewRect, te);
  301.     end;
  302.  
  303.     procedure TEStaticObject.DoActivateDeactivate (activate: boolean);
  304.     begin
  305.         if drawgrow then
  306.             DrawGrowIcon(window);
  307.         if activate then
  308.             TEActivate(te)
  309.         else
  310.             TEDeactivate(te);
  311.     end;
  312.  
  313. { Common algorithm for pinning the value of a control. It returns the actual amount }
  314. { the value of the control changed. }
  315.     procedure CommonAction (control: ControlHandle; var amount: integer);
  316.         var
  317.             value, max: integer;
  318.     begin
  319.         value := GetCtlValue(control);
  320.         max := GetCtlMax(control);
  321.         amount := value - amount;
  322.         if (amount <= 0) then
  323.             amount := 0
  324.         else if (amount >= max) then
  325.             amount := max;
  326.         SetCtlValue(control, amount);
  327.         amount := value - amount;   { calculate true change }
  328.     end; { CommonAction  }
  329.  
  330.     var
  331.         actionTE: TEHandle;
  332.  
  333. { Determines how much to change the value of the vertical scrollbar by and how }
  334. { much to scroll the TE record.}
  335.     procedure VActionProc (control: ControlHandle; part: integer);
  336.         var
  337.             amount: integer;
  338.             window: WindowPtr;
  339.     begin
  340.         if (part <> 0) then begin
  341.             window := control^^.contrlOwner;
  342.             case part of
  343.                 inUpButton, inDownButton:        { one line  }
  344.                     amount := 1;
  345.                 inPageUp, inPageDown:            { one page  }
  346.                     with actionTE^^, viewRect do
  347.                         amount := (bottom - top) div lineHeight;
  348.             end;
  349.             if ((part = inDownButton) or (part = inPageDown)) then
  350.                 amount := -amount;        { reverse direction for a downer  }
  351.             CommonAction(control, amount);
  352.             if (amount <> 0) then
  353.                 TEScroll(0, amount * actionTE^^.lineHeight, actionTE);
  354.         end;
  355.     end; { VActionProc }
  356.  
  357. { Determines how much to change the value of the horizontal scrollbar by and how }
  358. { much to scroll the TE record. }
  359.     procedure HActionProc (control: ControlHandle; part: integer);
  360.         var
  361.             amount: integer;
  362.             window: WindowPtr;
  363.     begin
  364.         if (part <> 0) then begin
  365.             window := control^^.contrlOwner;
  366.             case part of
  367.                 inUpButton, inDownButton:        { a few pixels }
  368.                     amount := 8;
  369.                 inPageUp, inPageDown:            { a page width }
  370.                     with actionTE^^.viewRect do
  371.                         amount := (right - left);
  372.             end;
  373.             if ((part = inDownButton) or (part = inPageDown)) then
  374.                 amount := -amount;        { reverse direction }
  375.             CommonAction(control, amount);
  376.             if (amount <> 0) then
  377.                 TEScroll(amount, 0, actionTE);
  378.         end;
  379.     end; { HActionProc }
  380.  
  381. { Gets called from CallClickLoop which in turn }
  382. { is called by the TEClick toolbox routine. Saves the window's clip region, }
  383. { sets it to the portRect, adjusts the scrollbar values to match the TE scroll }
  384. { amount, then restores the clip region. }
  385.     procedure TEStaticObject.ClickLoop;
  386.         var
  387.             region: RgnHandle;
  388.             vc, hc: integer;
  389.     begin
  390.         SetPort(window);
  391.         region := NewRgn;
  392.         GetClip(region);                { save the old clip }
  393.         ClipRect(window^.portRect);        { set the new clip }
  394.         vc := AdjustHV(true, vcontrol, te, false);
  395.         hc := AdjustHV(false, hcontrol, te, false);
  396.         SetClip(region);                { restore the old clip }
  397.         DisposeRgn(region);
  398.     end; { PascalClikLoop }
  399.  
  400.     function TEStaticObject.WordBreak (text: ptr; pos: integer; forward: boolean): boolean;
  401.     begin
  402.         if forward then
  403.             WordBreak := (pos > 0) and (ptr(longInt(text) + pos - 1)^ = 13)
  404.         else
  405.             WordBreak := ptr(longInt(text) + pos)^ = 13
  406.     end;
  407.  
  408.     procedure TEStaticObject.DoItemWhere (er: eventRecord; item: integer);
  409.         var
  410.             control: controlHandle;
  411.             value, part: integer;
  412.     begin
  413.         SetPort(window);
  414.         GlobalToLocal(er.where);
  415.         part := FindControl(er.where, window, control);
  416.         if part = 0 then begin
  417.             if PtInRect(er.where, te^^.viewRect) then
  418.                 Click(er.where, BAND(er.modifiers, shiftKey) <> 0)
  419.         end
  420.         else begin
  421.             if part = inThumb then begin
  422.                 value := GetCtlValue(control);
  423.                 part := TrackControl(control, er.where, nil);
  424.                 if part <> 0 then begin
  425.                     value := value - GetCtlValue(control);
  426.                     if value <> 0 then
  427.                         if control = vcontrol then
  428.                             TEScroll(0, value * te^^.lineHeight, te)
  429.                         else
  430.                             TEScroll(value, 0, te);
  431.                 end;
  432.             end
  433.             else begin
  434.                 actionTE := te;
  435.                 if control = vcontrol then
  436.                     value := TrackControl(control, er.where, @VActionProc)
  437.                 else
  438.                     value := TrackControl(control, er.where, @HActionProc);
  439.             end;
  440.         end;
  441.     end;
  442.  
  443.     function TEStaticObject.EditMenuEnabled: boolean;
  444.         var
  445.             i: integer;
  446.     begin
  447.         for i := EMundo to EMselectall do
  448.             if i <> EMundo + 1 then
  449.                 SetEditMenuItem(i);
  450.         EditMenuEnabled := (te^^.selStart < te^^.selEnd) or (te^^.teLength > 0);
  451.     end;
  452.  
  453.     procedure TEStaticObject.SetEditMenuItem (item: integer);
  454.     begin
  455.         case item of
  456.             EMundo, EMcut, EMpaste, EMclear:  { Can't undo, cut, copy, paste in a static edit thingy }
  457.                 SetIDItemEnable(M_Edit, item, false);
  458.             EMcopy: 
  459.                 SetIDItemEnable(M_Edit, item, te^^.selStart < te^^.selEnd);  { Can copy iff there is a selection }
  460.             EMselectall: 
  461.                 SetIDItemEnable(M_Edit, item, te^^.teLength > 0);  { Can select all iff there is something to select }
  462.             otherwise
  463.         end;
  464.     end;
  465.  
  466.     procedure TEStaticObject.DoEditMenu (item: integer);
  467.         var
  468.             oe: OSErr;
  469.             loe: longInt;
  470.     begin
  471.         case item of
  472.             EMcopy:  begin
  473.                 TECopy(te);
  474.                 loe := ZeroScrap;
  475.                 oe := TEToScrap;
  476.             end;
  477.             EMselectall:  begin
  478.                 SetPort(window);
  479.                 TESetSelect(0, maxLongInt, te);
  480.             end;
  481.             otherwise
  482.         end;
  483.     end;
  484.  
  485.     procedure TEStaticObject.DoIdle;
  486.     begin
  487.         TEIdle(te);
  488.     end;
  489.  
  490.     procedure TEStaticObject.DoKey (modifiers: integer; ch: char);
  491.     begin
  492.         if BAND(modifiers, cmdKey) = 0 then
  493.             TEKey(ch, te);
  494.         Adjust;
  495.     end;
  496.  
  497. end.